package interaction

import (
	"time"

	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/common"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/factory"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/interactiond"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"
)

type reqOp struct {
	Value      int                       `json:"value"`       // 值
	TargetID   string                    `json:"target_id"`   //　目标
	TargetType interactiond.IGTargetType `json:"target_type"` // 　类型
}

func (c interactionCtrl) putOp(ctx *gin.Context) {
	code := ctx.Param("code")
	if code == "" {
		c.ErrBadRequest(ctx, 1, "参数错误")
		return
	}
	var req reqOp
	if err := ctx.BindJSON(&req); err != nil {
		c.ErrBadRequestByBind(ctx, 2, err)
		return
	}

	dctx := c.DDDContext(ctx)
	uid := dctx.UID()
	if uid == "" {
		c.ErrUnauthorized(ctx, "保存失败：未登录")
		return
	}
	err := c.addOp(dctx, uid, code, req)
	if err != nil {
		c.ErrServerError(ctx, 4, "保存失败", err)
	}
	c.Success(ctx, nil)
}

func (c interactionCtrl) addOp(dctx ddd.Context, uid, code string, req reqOp) error {

	t, err := c.tar.GetType(dctx, code)
	if err != nil {
		return errors.Wrapf(err, "请求互动类型(%v)失败", code)
	}
	if t == nil {
		return errors.Errorf("互动类型(%v)不存在", code)
	}

	if t.Max < req.Value || t.Min > req.Value {
		return errors.Errorf("参数错误:value必须在 %d-%d之间", t.Min, t.Max)
	}

	g, err := factory.DefaultFactory.GetOrCreIGroup(dctx, req.TargetType, req.TargetID)
	if err != nil {
		return errors.Wrapf(err, "获取互动组(%03d-%v)失败", req.TargetType, req.TargetID)
	}
	flag := false
	for _, v := range g.AllowCodes {
		if v == code {
			flag = true
			break
		}
	}
	if !flag {
		return ErrForbid
	}
	switch t.Mode {
	case interactiond.ITModeCount:
		// 累计
		desc := interactiond.InteractionDesc{
			IGID:  g.IGID,
			UID:   uid,
			Code:  code,
			Value: req.Value,
		}
		if _, err = c.iiar.AddInteraction(dctx, desc); err != nil {
			return errors.Wrapf(err, "保存交互信息失败")
		}
	case interactiond.ITModeOne:

		_, rs, err := c.iiar.QueryPage(dctx, interactiond.InteractionSearch{
			IGID:  []string{g.IGID},
			UID:   []string{uid},
			Codes: []string{code},
		}, common.PageInfo{PageSize: 1})
		if err != nil {
			return errors.Wrapf(err, "获取互动信息(%03d-%v)失败", req.TargetType, req.TargetID)
		}
		if len(rs) > 0 {
			if rs[0].Value != req.Value {
				// 需要更新
				if err := rs[0].UpdateValue(dctx, req.Value); err != nil {
					return errors.Wrapf(err, "保存交互信息失败")
				}
			}
		} else {
			desc := interactiond.InteractionDesc{
				IGID:  g.IGID,
				UID:   uid,
				Code:  code,
				Value: req.Value,
			}
			if _, err = c.iiar.AddInteraction(dctx, desc); err != nil {
				return errors.Wrapf(err, "保存交互信息失败")
			}
		}
	}
	return nil
}
func (c interactionCtrl) deleteOp(dctx ddd.Context, uid, code string, req reqOp) error {

	t, err := c.tar.GetType(dctx, code)
	if err != nil {
		return errors.Wrapf(err, "请求互动类型(%v)失败", code)
	}
	if t == nil {
		return errors.Errorf("互动类型(%v)不存在", code)
	}
	g, err := factory.DefaultFactory.GetOrCreIGroup(dctx, req.TargetType, req.TargetID)
	if err != nil {
		return errors.Wrapf(err, "获取互动组(%03d-%v)失败", req.TargetType, req.TargetID)
	}
	flag := false
	for _, v := range g.AllowCodes {
		if v == code {
			flag = true
			break
		}
	}
	if !flag {
		return errors.New("禁止该操作")
	}
	switch t.Mode {
	case interactiond.ITModeCount:
		return errors.Wrapf(err, "该类型禁止该操作")

	case interactiond.ITModeOne:

		_, rs, err := c.iiar.QueryPage(dctx, interactiond.InteractionSearch{
			IGID:  []string{g.IGID},
			UID:   []string{uid},
			Codes: []string{code},
		}, common.PageInfo{PageSize: 1})
		if err != nil {
			return errors.Wrapf(err, "获取互动信息(%03d-%v)失败", req.TargetType, req.TargetID)
		}
		if len(rs) == 0 {
			return nil
		}
		return rs[0].Delete(dctx)
	}
	return nil
}

func (c interactionCtrl) getOpSearch(ctx *gin.Context) (result interactiond.InteractionSearch) {
	result.IGID = ctx.QueryArray("igid")
	ok := false
	result.Codes, ok = ctx.GetQueryArray("code")
	if !ok {
		result.Codes = make([]string, 0)
	}
	return
}

type respOp struct {
	ID      string    `json:"id"`       // 互动ｉｄ
	IGID    string    `json:"igid"`     // 互动组ID
	Code    string    `json:"code"`     // 类型
	UID     string    `json:"uid"`      // 互动用户
	Value   int       `json:"value"`    // 值
	CreTime time.Time `json:"cre_time"` // 创建时间
}

func (c interactionCtrl) queryPageOps(ctx *gin.Context) {
	sch := c.getOpSearch(ctx)

	dctx := c.DDDContext(ctx)
	uid := dctx.UID()
	if uid == "" {
		c.ErrUnauthorized(ctx, "保存失败：未登录")
		return
	}
	sch.UID = []string{uid}
	c.queryPageInteraction(ctx, dctx, sch)
}

func (c interactionCtrl) queryPageOpsByCode(ctx *gin.Context) {

	code := ctx.Param("code")
	if code == "" {
		c.ErrBadRequest(ctx, 1, "参数错误")
		return
	}
	sch := c.getOpSearch(ctx)
	sch.Codes = []string{code}
	dctx := c.DDDContext(ctx)
	uid := dctx.UID()
	if uid == "" {
		c.ErrUnauthorized(ctx, "保存失败：未登录")
		return
	}
	c.queryPageInteraction(ctx, dctx, sch)
}

func (c interactionCtrl) queryPageMyOpsByCode(ctx *gin.Context) {

	code := ctx.Param("code")
	if code == "" {
		c.ErrBadRequest(ctx, 1, "参数错误")
		return
	}
	sch := c.getOpSearch(ctx)
	sch.Codes = []string{code}
	dctx := c.DDDContext(ctx)
	uid := dctx.UID()
	if uid == "" {
		c.ErrUnauthorized(ctx, "保存失败：未登录")
		return
	}
	sch.UID = []string{uid}
	c.queryPageInteraction(ctx, dctx, sch)
}
func (c interactionCtrl) queryPageInteraction(ctx *gin.Context, dctx ddd.Context, sch interactiond.InteractionSearch) {
	page := c.GetPageInfo(ctx, common.PageModeID)
	pr, cs, err := c.iiar.QueryPage(dctx, sch, page)
	if err != nil {
		c.ErrServerError(ctx, 3, "查询失败", errors.Wrapf(err, "查询互动交互列表失败"))
		return
	}
	out := make([]respOp, 0, len(cs))
	for _, v := range cs {
		out = append(out, respOp{
			ID:      v.InteractionID,
			IGID:    v.IGID,
			Code:    v.Code,
			UID:     v.UID,
			Value:   v.Value,
			CreTime: v.CreTime,
		})
	}
	c.SuccessPage(ctx, page, pr, out)
}
